#!/usr/bin/env python
#
# Example of an experiment using Virtual Organization Clusters with the Xen
# hypervisor. Xen overheads are computed according to reference [1].
#
# Author:   Mike Murphy (mamurph@cs.clemson.edu)
# Revision: 23 September 2009
#
#   Copyright 2009 Clemson University
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
#
# This material is based upon work supported under a National Science
# Foundation Graduate Research Fellowship. Any opinions, findings,
# conclusions or recommendations expressed in this publication are those of
# the author(s) and do not necessarily reflect the views of the National
# Science Foundation.
#
# References:
# [1] M. Fenn, M. Murphy, and S. Goasguen. "A Study of a KVM-based Cluster
#     for Grid Computing." 47th ACM Southeast Conference (ACMSE '09), Clemson,
#     SC, March 2009.

# File paths for simulator I/O
import os, os.path

HOME = os.getenv('HOME')

# Adjust these paths for input/output locations
INPUT_PATH = os.path.join(HOME, 'hg/simvoc_input_2/')
OUTPUT_FILE = os.path.join(HOME, 'simulations/ipdps-xen.sq3')

# Experiment parameters
from simvoc.core.units import *

VM_IMAGE_SIZE = 15*u_GiB
CE_SPEED = 1*u_Gbps
FS_SPEED = 1*u_Gbps
VOC_SCHEDULER = 'condor'

# KVM overheads from [1]
CPU_OVERHEAD = 0.06566
NET_OVERHEAD = 0.22935
NET_BOUND = 50   # Estimated
BOOT_TIME = 65.5

# Simulator components
from simvoc.core.aggregator import Aggregator
from simvoc.core.cluster_sim import MachineFactory
from simvoc.core.db_output import DBOutput
from simvoc.core.duplicate_filter import DuplicateFilter
from simvoc.core.egee_schedulers import new_egee_scheduler
from simvoc.core.filter_results import ResultFilter
from simvoc.core.grid_sim import Grid
from simvoc.core.input_manager import JOB, MAP, VO, flex_loader
from simvoc.core.kernel import Simulator
from simvoc.core.metascheduler import Metascheduler
from simvoc.core.results import kernel_trace, kernel_metadata
from simvoc.core.storage import FileStore
from simvoc.core.virtualization import VMHost
from simvoc.core.voc_sim import AutoVOC, job_rewrite_to_vo
from simvoc.core.watchdog_sim import Watchdog

# Output pipeline
result_filter = [ 'Aggregation', 'Discard', 'Job', 'Metadata', 'Site',
                  'SiteRejection', 'Trace', 'VO', 'VOC' ]
#
db_out = DBOutput(OUTPUT_FILE)
sel = ResultFilter(result_filter, db_out)
agg = Aggregator(sel)
df = DuplicateFilter(agg)
out_h = df

# Main simulator instance
sim = Simulator(output_handler=out_h, ktrace=kernel_trace, \
                kmeta=kernel_metadata)
#

# Core grid
mf = MachineFactory(VMHost, vmm_name='Xen', sim=sim, cpu_oh=CPU_OVERHEAD, \
                    net_oh=NET_OVERHEAD, net_bound=NET_BOUND)
ms = Metascheduler(sim)
grid = Grid('EGEE', sim, new_egee_scheduler, metasched=ms, \
            machine_factory=mf, ce_speed=CE_SPEED)
#

# VOC creation
fs = FileStore('VMStore', sim, FS_SPEED)
av = AutoVOC(grid, fs, VM_IMAGE_SIZE, VOC_SCHEDULER, BOOT_TIME, Watchdog, \
             sim=sim, q_sched=ms)
#

# Input file handling
fi = flex_loader(sim, grid, av, jobmodfn=job_rewrite_to_vo)
fi.load(INPUT_PATH, JOB, extension='.jobs')
fi.load(INPUT_PATH, MAP, extension='.map')
fi.load(INPUT_PATH, VO, extension='.vo')
fi.normalize()

# Actual execution
sim.run()

# Cleanup
fi.close()
out_h.close()
